package base;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Classe permettant de construire les statistiques de base pour chacune des catégories
 * sur le fichier train.txt
 */
public class Base {

	/**
	 * Le nombre total de tweets
	 */
	private int nbTweets;
	
	/**
	 * Le vocabulaire : liste de tous les mots
	 */
	private ArrayList<String> vocabulaire;
	
	/**
	 * La catégorie "positive"
	 */
	private Category positive;
	
	/**
	 * La catégorie "negative"
	 */
	private Category negative;
	
	/**
	 * La catégorie "neutral"
	 */
	private Category neutral;
	
	/**
	 * La catégorie "irrelevant"
	 */
	private Category irrelevant;
	
	/**
	 * La catégorie intermédiaire "relevant"
	 */
	private Category relevant;

	/**
	 * Le chemin du fichier considéré
	 */
	private String filePath;
	
	/**
	 * La liste des tweets
	 */
	private ArrayList<Tweet> tweets;

	
	/**
	 * Constructeur d'un objet Base
	 * @param filePath le chemin du fichier à considérer
	 */
	public Base(String filePath) {
		this.filePath = filePath;
		vocabulaire = new ArrayList<String>();
		nbTweets = 0;
		positive = new Category();
		negative = new Category();
		neutral = new Category();
		irrelevant = new Category();
		relevant = new Category();
		tweets = new ArrayList<Tweet>();
	}

	/**
	 * Renvoie le vocabulaire
	 * @return le vocabulaire
	 */
	public ArrayList<String> getVocabulaire() {
		return vocabulaire;
	}
	
	/**
	 * Renvoie le nombre total de tweets
	 * @return le nombre total de tweets
	 */
	public int getNbTweets() {
		return this.nbTweets;
	}
	
	/**
	 * Renvoie la catégorie positive
	 * @return la catégorie positive
	 */
	public Category getPositive() {
		return this.positive;
	}
	
	/**
	 * Renvoie la catégorie negative
	 * @return la catégorie negative
	 */
	public Category getNegative() {
		return this.negative;
	}
	
	/**
	 * Renvoie la catégorie neutral
	 * @return la catégorie neutral
	 */
	public Category getNeutral() {
		return this.neutral;
	}
	
	/**
	 * Renvoie la catégorie irrelevant
	 * @return la catégorie irrelevant
	 */
	public Category getIrrelevant() {
		return this.irrelevant;
	}
	
	/**
	 * Renvoie la catégorie relevant
	 * @return la catégorie relevant
	 */
	public Category getRelevant() {
		return this.relevant;
	}
	
	/**
	 * Parcourt le fichier considéré et crée un objet Tweet pour chaque tweet, avec les attributs correspondants
	 */
	public void construireBase() {
		
		BufferedReader reader = null;
		
		try {
			FileInputStream file = new FileInputStream(filePath); 
			InputStreamReader isr = new InputStreamReader(file, "UTF-8"); 
			
			reader = new BufferedReader(isr);
			String tempStr = null;
			int line = 1;
			
			/* On parcourt le fichier ligne par ligne */
			while ((tempStr = reader.readLine()) != null) {
				String[] valeurs = tempStr.split("\",\"");
				
				/* Si une ligne contient moins de cinq champs, on passe directement à la ligne suivante */
				if(valeurs.length < 5)
					continue;
				
				String topic = valeurs[0];
				String classType = valeurs[1];
				String message = valeurs[4];
				
				topic = topic.replace("\"", "");
				message = message.replace("\"", "");
				
				/* Si le sentiment n'est pas reconnu, on passe directement à la ligne suivante */
				if(! this.valideTypeClass(classType))
					continue;
					
				this.nbTweets ++;
				
				Tweet tweet = new Tweet(line, topic, classType, message);
				tweets.add(tweet);
				
				/* On supprime les caractères spéciaux */
				//Pattern p = Pattern.compile("[^0-9a-zA-Z]");
				Pattern p = Pattern.compile("[,.!?\":]");
				Matcher m = p.matcher(message);
				message = m.replaceAll(" ");

				String[] mots = message.split(" ");
				ArrayList<String> motsList = new ArrayList<String>();
				
				/* On parcourt la liste des mots de chaque tweet pour construire le vocabulaire */
				for(int i = 0; i < mots.length ; i ++) {
					motsList.add(mots[i]);
					if(!this.vocabulaire.contains(mots[i]))
						this.vocabulaire.add(mots[i]);
				}
				
				/* Classe les tweets selon leur catégorie */
				if(classType.compareTo("positive")==0) {
					positive.traiterUnTweet(motsList);
					relevant.traiterUnTweet(motsList);
				}
				else if(classType.compareTo("negative")==0) {
					negative.traiterUnTweet(motsList);
					relevant.traiterUnTweet(motsList);
				}
				else if(classType.compareTo("neutral")==0) {
					neutral.traiterUnTweet(motsList);
					relevant.traiterUnTweet(motsList);
				}
				else if(classType.compareTo("irrelevant")==0)
					irrelevant.traiterUnTweet(motsList);
				
				line++;
			}
			
			finirBase();
			reader.close();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		finally {
			if (reader != null) {
				try {
					reader.close();
				}
				catch (IOException e1) {
				}
			}
		}
	}
	
	/**
	 * Finit de construire les statistiques
	 */
	private void finirBase() {
		ArrayList<Category> categories = new ArrayList<Category>();
		categories.add(irrelevant);
		categories.add(relevant);
		relevant.finirTraitement(categories, nbTweets);
		irrelevant.finirTraitement(categories,nbTweets);
		
		categories.remove(relevant);
		
		categories.add(positive);
		categories.add(negative);
		categories.add(neutral);
		
		positive.finirTraitement(categories, nbTweets);
		negative.finirTraitement(categories, nbTweets);
		neutral.finirTraitement(categories, nbTweets);
	}
	
	/**
	 * Renvoie si le sentiment du tweet est valide ou non
	 * @param typeClass le sentiment
	 * @return true si le sentiment est valide, false sinon
	 */
	private boolean valideTypeClass(String typeClass) {
		if(typeClass.compareTo("positive")==0
				|| typeClass.compareTo("negative")==0
				|| typeClass.compareTo("neutral")==0
				|| typeClass.compareTo("irrelevant")==0)
			return true;
		else
			return false;
	}
	
	/**
	 * Renvoie le tweet correspondant à l'index donné en paramètre
	 * @param index l'index du tweet
	 * @return le tweet correspondant à l'index
	 */
	public Tweet getTweet(int index) {
		return tweets.get(index);
	}
	
	/**
	 * Main : 
	 * Parcourt le fichier train.txt et construit les statistiques de base pour chacune des catégories
	 * @param args
	 */
	public static void main(String[] args) {
		Base base = new Base("fichiers/train.txt");
		base.construireBase();
		System.out.println(base.getRelevant().getNbDoc());
	}
}
